/**
 *   Copyright (C) 2021 All rights reserved.
 *
 *   FileName      ：main.cpp
 *   Author        ：hpy
 *   Email         ：yuan_hp@qq.com
 *   Date          ：2021年06月26日
 *   Description   ：
 */

#include <bits/stdc++.h>
#include <cmath>
using namespace std;

#define TAN 0
#define SIN 1
#define COS 2
#define TANH 3
#define SQURE 4   //平方  y=x*x
#define INVERSE 5  // y=1/x
#define LN 6   //
#define ARCSIN 7


#define DATA_SRC INVERSE    //定义数据源， sin cos tan等

//==================================
#define N 256   //数据源

#define STEP 2  // 抽样数据间隔
#define RANDPARAM 5 //最大模拟读数的x的增量

#define A 65535
#define PI 3.1415926
//--------------------- 关键代码 -------------------------------
//pData,pTime 前面至少两个数据，后面至少3个数据，
//dTime位于*pTime,*(pTime+1)之间（*pTime<=dTime<*(pTime+1)）
int AkimaIntercpolation(int *pData, int *pTime, int dTime)
{
	double Mk, Mka1,Mka2, Mks1, Mks2,tk,tka1,Value,delta;
	Mk = (double)(*(pData + 1) - *(pData)) / (*(pTime + 1) - *(pTime));
	Mka1 = (double)(*(pData + 2) - *(pData+1)) / (*(pTime + 2) - *(pTime+1));
	Mka2 = (double)(*(pData + 3) - *(pData + 2)) / (*(pTime + 3) - *(pTime + 2));
	Mks1 = (double)(*(pData) - *(pData-1)) / (*(pTime) - *(pTime-1)); 
	Mks2 = (double)(*(pData -1) - *(pData-2)) / (*(pTime -1) - *(pTime-2));
	tk = (fabs(Mka1 - Mk)*Mks1 + fabs(Mks1 - Mks2)*Mk) / max(0.01,(fabs(Mka1 - Mk) + fabs(Mks1 - Mks2)));
	tka1 = (fabs(Mka2 - Mka1)*Mk + fabs(Mk - Mks1)*Mka1) / max(0.01,(fabs(Mka2 - Mka1) + fabs(Mk - Mks1)));
	double c0, c1, c2, c3;
	c0 = *pData;
	c1 = tk;
	c2 = (3 * Mk - 2 * tk - tka1) / (*(pTime + 1) - *(pTime));
	c3 = (tk + tka1-2*Mk) / ((*(pTime + 1) - *(pTime))*(*(pTime + 1) - *(pTime)));
	delta = dTime - *pTime;
	Value = c0 + c1*delta + c2*delta*delta + c3*delta*delta*delta;
	int iValue;
	iValue=(int)Value;
	if ((iValue < -18588608) || (iValue > 18588608)) {
		Value = Value;
	}
	return iValue;
}

int data[N];
void MakeSinData() {
	char *fid = "data.txt" ; 
	ofstream fout(fid);
	for(int i = 0; i<N ; ++i) {
#if(DATA_SRC == TAN)
		data[i] = A*tan(2*PI/N*i);
#elif( DATA_SRC == SIN )
		data[i] = A*sin(2*PI/N*i);
#elif( DATA_SRC == TANH )
		data[i] = A*tanh(2*PI/N*i);
#elif( DATA_SRC == COS )
		data[i] = A*cos(2*PI/N*i);
#elif( DATA_SRC == SQURE )
		data[i] = i*i;
#elif( DATA_SRC == INVERSE )
		data[i] = A*1.0/(i+1);
#elif( DATA_SRC == LN )
		data[i] = A*log(i+10);
#elif( DATA_SRC == ARCSIN )
		data[i] = A*asin(1.0*i/N);
#else 
		data[i] = A*sin(2*PI/N*i);
#endif 

		if(fout.is_open()){
			fout << i << " " << data[i] << endl;
    	}
	}

	fout.close();
}

int y[N] ; 
int x[N], x_len ;
int dx[N]  ;
int num = 0; 
void MakeTestData(){

	int j = 0 ;
	x_len = 0;
	char *fid = "sampData.txt" ; 
	ofstream fout(fid);
	for(int i =0; i < N ; i++ ) {
		if(i%STEP == 0 ) {
			y[j] = data[i];
			x[j] = i;
			j++;
			x_len++;
			fout << i << " " << data[i] << endl;
		}
	}
	fout.close();
}

// 将要插值的目标点
void MakePulse(){
	int i = 0;
	int idx = 0;
	num = 0;
	while(1) {
		int t = idx + RANDPARAM ; 
		if (t > idx ) idx = t ; 
		else continue ;
		if(idx < x[x_len-1] ) {
			dx[num++] = idx;
			cout<<idx <<endl;
		} else {
			break;
		}
	}
	cout<<"idx = " <<idx <<endl; 

}

int outY[N] ;
int outX[N] ;
int outLen =0;
void MakeAkAns(){
	int dx_st = 0;
	int x_st = 3;
	outLen = 0;
	while ( (dx[dx_st] <= x[x_st]) && (dx_st < num) ) dx_st++; //保证起始的第一个脉冲时标大于第一个AD时标
	while ((dx_st < num - 2) && (x_st < x_len - 3) ) {
		while ((dx[dx_st] >= x[x_st]) && (x_st < x_len - 3)) x_st++;//找到脉冲时标后的第一个AD
		x_st--;
		while ((dx[dx_st] < x[x_st]) && (x_st < x_len - 3)) x_st--;//找到脉冲时标后的第一个AD
		{
			outY[outLen] = (int)AkimaIntercpolation( y + x_st, x + x_st, dx[dx_st] );//
			outX[outLen] = dx[dx_st]; 
			outLen++;
		}
		dx_st++;
	}

	char *fid = "out.txt" ; 
	ofstream fout(fid);
	for(int i=0;i<outLen ; ++i) {
		fout << outX[i] << " " << outY[i] <<endl;
	}
	fout.close();
}

int main(int argc, char* argv[])
{
	cout << "AKima插值算法测试"<< endl ; 
	MakeSinData();
	MakeTestData();
	MakePulse();
	MakeAkAns();
	return 0;
}

